<script lang="ts" setup>
import { QForm, type FormItemRows } from '@meetjs/element-plus-kit'
import type { FormRules, RenderContentContext, TreeInstance } from 'element-plus'
import type { IGetDictsRes } from '@/api/system/dict/type'
import { roleMenuTreeselect, treeselect } from '@/api/system/menu'
import { addRole, getRole, updateRole } from '@/api/system/role'
import type { RoleParams } from '@/api/system/role/type'
import type { TreeMenu } from '@/api/system/menu/type'

const userId = ref<number | undefined>()
const menuExpand = ref(false)
const props = defineProps<{
	sysNormalDisable: IGetDictsRes
}>()
const emits = defineEmits<{
	refresh: []
}>()
const visible = ref(false)
const loading = ref(false)
const formLoading = ref(false)
const btnLoading = computed(() => loading.value || formLoading.value)

const title = ref<'新增角色' | '修改角色'>('新增角色')
// TODO:后续优化类型
const formRef = ref()
const baseFormData: RoleParams = {
	menuCheckStrictly: true,
	deptCheckStrictly: false,
	menuIds: [],
	roleName: '',
	roleKey: '',
	roleSort: 0,
	status: 0,
	remark: '',
	dataScope: 1,
	deptIds: []
}

const dialogFormValue = ref<RoleParams>({ ...baseFormData })
const dialogOptions = ref<FormItemRows[]>([
	{
		type: 'input',
		label: '角色名称',
		prop: 'roleName'
	},

	{
		type: 'input',
		label: '权限字符',
		prop: 'roleKey'
	},
	{
		type: 'input-number',
		label: '角色顺序',
		prop: 'roleSort',
		attrs: {
			min: 0,
			controlsPosition: 'right'
		}
	},
	{
		type: 'radio',
		label: '状态',
		prop: 'status',
		options: []
	},
	{
		type: 'slot',
		prop: 'expanded',
		label: '菜单权限'
	},
	{
		type: 'textarea',
		label: '备注',
		prop: 'remark',
		attrs: {
			rows: 3
		}
	}
])

watch(
	() => props.sysNormalDisable,
	() => {
		dialogOptions.value[3].options = props.sysNormalDisable
	}
)

const rules = ref<FormRules<{ [k: string]: any }>>({
	roleName: [
		{
			required: true,
			message: '请输入角色名称'
		}
	],
	roleKey: [
		{
			required: true,
			message: '请输入权限字符'
		}
	],
	roleSort: [
		{
			required: true,
			message: '请输入角色顺序'
		}
	]
})

const init = async (type: 'add' | 'edit', editUserId?: number) => {
	visible.value = true
	formRef.value?.resetFields()
	title.value = type === 'add' ? '新增角色' : '修改角色'
	dialogFormValue.value = { ...baseFormData }
	userId.value = editUserId
	if (!editUserId) {
		const { data } = await treeselect()
		menuOptions.value = data
		return
	}
	try {
		formLoading.value = true
		const res = await roleMenuTreeselect(editUserId)
		const { checkedKeys, menus } = res.data
		menuOptions.value = menus
		const { data } = await getRole(editUserId)
		dialogFormValue.value = data
		dialogFormValue.value.roleSort = Number(data.roleSort)
		checkedKeys.forEach(v => menuRef.value!.setChecked(v, true, false))
	} finally {
		formLoading.value = false
		setTimeout(() => {
			formRef.value?.clearValidate()
		})
	}
}
/** 所有菜单节点数据 */
function getMenuAllCheckedKeys() {
	// 目前被选中的菜单节点
	let checkedKeys = menuRef.value!.getCheckedKeys()
	// 半选中的菜单节点
	let halfCheckedKeys = menuRef.value!.getHalfCheckedKeys()
	checkedKeys.unshift.apply(checkedKeys, halfCheckedKeys)
	return checkedKeys as number[]
}

const submit = () => {
	formRef.value?.validate(async (valid: boolean) => {
		if (valid) {
			try {
				loading.value = true
				dialogFormValue.value.menuIds = getMenuAllCheckedKeys()
				const apiFunc = title.value === '新增角色' ? addRole : updateRole
				await apiFunc({ ...dialogFormValue.value })
				const message = title.value === '新增角色' ? '新增成功' : '修改成功'
				ElMessage.success(message)
				visible.value = false
				emits('refresh')
			} finally {
				loading.value = false
			}
		}
	})
}

const menuOptions = ref<TreeMenu[]>([])
const menuRef = useTemplateRef<TreeInstance>('menuRef')
const menuNodeAll = ref(false)
type Node = RenderContentContext['node']
/** 树权限（全选/全不选） */
function handleCheckedTreeNodeAll(value: string | number | boolean) {
	menuRef.value?.setCheckedNodes(value ? (menuOptions.value as unknown as Node[]) : [])
}

/** 树权限（展开/折叠）*/
function handleCheckedTreeExpand(value: string | number | boolean) {
	let treeList = menuOptions.value
	for (let i = 0; i < treeList.length; i++) {
		menuRef.value!.store.nodesMap[treeList[i].id].expanded = !!value
	}
}
/** 树权限（父子联动） */
function handleCheckedTreeConnect(val: string | number | boolean) {
	dialogFormValue.value.menuCheckStrictly = !!val
}

defineExpose({
	init
})
</script>
<template>
	<ElDialog
		v-model="visible"
		:title="title"
		:close-on-click-modal="false"
		width="800px"
	>
		<div v-loading="formLoading">
			<QForm
				ref="formRef"
				label-width="120px"
				:model="dialogFormValue"
				:form-options="dialogOptions"
				:rules="rules"
			>
				<template #expanded>
					<div>
						<el-checkbox
							v-model="menuExpand"
							@change="handleCheckedTreeExpand($event)"
						>
							展开/折叠
						</el-checkbox>
						<el-checkbox
							v-model="menuNodeAll"
							@change="handleCheckedTreeNodeAll"
						>
							全选/全不选
						</el-checkbox>
						<el-checkbox
							v-model="dialogFormValue.menuCheckStrictly"
							@change="handleCheckedTreeConnect"
						>
							父子联动
						</el-checkbox>
						<el-tree
							ref="menuRef"
							class="tree-border"
							:data="menuOptions"
							show-checkbox
							node-key="id"
							:check-strictly="!dialogFormValue.menuCheckStrictly"
							empty-text="加载中，请稍候"
							:props="{ label: 'label', children: 'children' }"
						/>
					</div>
				</template>
			</QForm>
		</div>
		<template #footer>
			<el-button @click="visible = false">取消</el-button>
			<el-button
				type="primary"
				:loading="btnLoading"
				@click="submit"
			>
				确定
			</el-button>
		</template>
	</ElDialog>
</template>

<style lang="scss" scoped></style>
